package com.un.ebs.businessObject.service.impl;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import com.un.ebs.sys.service.impl.TableWapper;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMethod;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.un.ebs.core.enums.ColumnRefTypeEnum;
import com.un.ebs.core.enums.DataTypeEnum;
import com.un.ebs.core.enums.RequestArgEnum;
import com.un.ebs.core.metadata.FunctionInfo;
import com.un.ebs.core.metadata.MetadataField;
import com.un.ebs.core.metadata.RequestArg;
import com.un.ebs.sys.domain.Column;
import com.un.ebs.sys.domain.Table;
import com.un.ebs.sys.enums.DisplayEnums;
import com.un.ebs.sys.enums.FunctionsEnums;
import com.un.ebs.sys.mapper.ColumnMapper;
import com.un.ebs.businessObject.service.RelGetByIdService;
import com.un.ebs.businessObject.service.RelService;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * @Author zc
 * @ClassName RelGetByIdService
 * @Description
 * @Date 2021/1/12
 */
@Slf4j
@Service
public class RelGetByIdServiceImpl implements RelGetByIdService {

	@Autowired
	private ColumnMapper columnMapper;

	@Autowired
	private RelService relService;

	@Override
	public FunctionInfo getByIdFunc(Table table) {
		FunctionInfo func = new FunctionInfo();
		String url = FunctionsEnums.GET_BY_ID.getUrl();
		String desc = FunctionsEnums.GET_BY_ID.getDesc();
		List<RequestMethod> method = Arrays.asList(FunctionsEnums.GET_BY_ID.getRequestMethod());

		func.setUrl(String.format(url, table.getId()));
		func.setDescription(desc);
		func.setMethod(method);
		func.setName(table.getTableName());

		List<RequestArg> requestArgs = new ArrayList<>();
		List<MetadataField> metadataFields = new ArrayList<>();
		LambdaQueryWrapper<Column> qw = new LambdaQueryWrapper<Column>();
		qw.eq(Column::getTableId, table.getId());
		List<Column> columns = columnMapper.selectList(qw);
		columns = columns.stream().filter(x -> !DisplayEnums.getColumnNameList().contains(x.getColumnName()))
				.collect(Collectors.toList()); // 过滤支持相关字段
		for (Column column : columns) {
			if (column.getIsPk()) {
				RequestArg requestArg = new RequestArg();
				requestArg.setName(column.getColumnName());
				requestArg.setDisplayName(column.getColumnDesc());
				requestArg.setDataType(column.getColumnType());
				requestArg.setIsArray(0);
				requestArg.setRequestType(RequestArgEnum.PathVariable);
				requestArgs.add(requestArg);
			}

			MetadataField metadataField = new MetadataField();
			metadataField.setName(column.getColumnName());
			metadataField.setDisplayName(column.getColumnDesc());
			metadataField.setDataType(column.getColumnType());
			metadataField.setIsArray(0);
			metadataFields.add(metadataField);

		}
		List<RequestArg> request = getListRequest(requestArgs);
		List<MetadataField> response = getListResponse(metadataFields);
		func.setRequest(request);
		func.setResponse(response);
		return func;
	}

	private List<MetadataField> getListResponse(List<MetadataField> metadataFields) {
		List<MetadataField> list = new ArrayList<>();
		// 1.构造code
		MetadataField m1 = new MetadataField();
		m1.setName("code");
		m1.setIsArray(0);
		m1.setDataType(DataTypeEnum.INT);
		// 2.构造message
		MetadataField m2 = new MetadataField();
		m2.setName("message");
		m2.setIsArray(0);
		m2.setDataType(DataTypeEnum.STRING);
		// 3.构造data
		MetadataField m3 = new MetadataField();
		m3.setName("data");
		m3.setIsArray(0);
		m3.setDataType(DataTypeEnum.OBJECT);
		m3.setChildField(metadataFields);
		list.add(m1);
		list.add(m2);
		list.add(m3);
		return list;
	}

	private List<RequestArg> getListRequest(List<RequestArg> requestArgs) {
		return requestArgs;
	}

	@Getter
	@Setter
	class Inner {
		/** 请求参数 */
		List<RequestArg> a = new ArrayList<>();
		/** 响应参数 */
		List<MetadataField> b = new ArrayList<>();
	}

	@Override
	public FunctionInfo getViewByIdFunc(Table table) {
		FunctionInfo func = new FunctionInfo();
		String url = FunctionsEnums.GET_VIEW_BY_ID.getUrl();
		String desc = FunctionsEnums.GET_VIEW_BY_ID.getDesc();
		List<RequestMethod> method = Arrays.asList(FunctionsEnums.GET_VIEW_BY_ID.getRequestMethod());

		func.setUrl(String.format(url, table.getId()));
		func.setDescription(desc);
		func.setMethod(method);
		func.setName(table.getTableName());

		List<RequestArg> requestArgs = new ArrayList<>();
		List<MetadataField> metadataFields = new ArrayList<>();
		LambdaQueryWrapper<Column> qw = new LambdaQueryWrapper<Column>();
		qw.eq(Column::getTableId, table.getId());
		List<Column> columns = columnMapper.selectList(qw);
		columns = columns.stream().filter(x -> !DisplayEnums.getColumnNameList().contains(x.getColumnName()))
				.collect(Collectors.toList()); // 过滤支持相关字段
		for (Column column : columns) {
			if (column.getIsPk()) {
				RequestArg requestArg = new RequestArg();
				requestArg.setName(column.getColumnName());
				requestArg.setDisplayName(column.getColumnDesc());
				requestArg.setDataType(column.getColumnType());
				requestArg.setIsArray(0);
				requestArg.setRequestType(RequestArgEnum.PathVariable);
				requestArgs.add(requestArg);
			}

			MetadataField metadataField = new MetadataField();
			metadataField.setName(column.getColumnName());
			metadataField.setDisplayName(column.getColumnDesc());
			metadataField.setDataType(column.getColumnType());
			metadataField.setIsArray(0);
			metadataFields.add(metadataField);
		}

		// List<RequestArg> request = getListRequest(requestArgs);
		// List<MetadataField> response = getListResponse(metadataFields);
		TableWapper tableWapper = new TableWapper(); // 子类转父类
		try {
			BeanUtils.copyProperties(tableWapper, table);
		} catch (IllegalAccessException | InvocationTargetException e) {
			log.error("getAddFunc转化table异常 error={}", e.getMessage());
			e.printStackTrace();
		}
		List<Table> tables = relService.getDbTables(table); // 获取所有表格
		relService.recursiveTable(tableWapper, tables, table.getId());

		Inner pInner = new Inner();
		pInner.setA(requestArgs);
		pInner.setB(metadataFields);
		this.procTableColumn(null, pInner, tableWapper); // 主表数据

		List<RequestArg> request = getListRequest(pInner.getA());
		List<MetadataField> response = getListResponse(pInner.getB());
		func.setRequest(request);
		func.setResponse(response);
		return func;
	}

	/**
	 * 处理表字段
	 * 
	 * @param arg   父级参数
	 * @param inner 父级inner
	 * @param table 父级table
	 */
	private void procTableColumn(MetadataField arg, Inner inner, TableWapper table) {
		// 处理子级对象
		List<TableWapper> list = table.getChilds();
		if (list != null && !list.isEmpty()) {
			for (TableWapper childTb : list) {
				MetadataField refRespArg = procChildData(arg, inner, table.getId(), table.getTableName(), childTb);
				// 递归子表
				this.procTableColumn(refRespArg, inner, childTb);
			}
		}
	}

	/**
	 * 处理下一级数据 只返回父级对象的id
	 * 
	 * @param inner     父表inner信息
	 * @param tableId   父表id
	 * @param tableName 父亲name
	 * @param table     子表
	 */
	private MetadataField procChildData(MetadataField arg, Inner inner, String tableId, String tableName,
			TableWapper table) {
		MetadataField refRespArg = null;
		LambdaQueryWrapper<Column> qw = Wrappers.lambdaQuery();
		qw.eq(Column::getTableId, table.getId());
		List<Column> columns = columnMapper.selectList(qw);

		// 返回参数
		List<MetadataField> metadataFields = new ArrayList<>();
		// 查出与父级表名一样的外键字段名称集合
		Set<String> refs = columns.stream()
				.filter(x -> (x.getRefTableName() != null && x.getRefTableName().equals(tableName))
						&& (x.getRefType() != null && ColumnRefTypeEnum.FK.equals(x.getRefType()))
						&& x.getRefColumnName() != null)
				.map(x -> x.getRefColumnName()).collect(Collectors.toSet());
		String refColumnName = refs.stream().findFirst().orElse(null);
		if (refColumnName != null) {
			for (Column column : columns) {
				MetadataField metadataField = new MetadataField();
				metadataField.setName(column.getColumnName());
				metadataField.setDisplayName(column.getColumnDesc());
				metadataField.setDataType(column.getColumnType());
				metadataField.setIsArray(0);
				metadataFields.add(metadataField);
			}

			// 新增外键虚拟列（默认只有一个外键）
			refRespArg = new MetadataField();
			refRespArg.setName(String.format("ref_%s|%s", table.getId(), refColumnName));
			refRespArg.setDisplayName(refRespArg.getName()); // 显示名称暂取Name
			refRespArg.setDataType(DataTypeEnum.OBJECT); // 对象
			refRespArg.setIsArray(1);
			refRespArg.setChildField(metadataFields); // 子级对象

			if (arg == null) {
				inner.getB().add(refRespArg);
			} else {
				List<MetadataField> fields = arg.getChildField();
				if (fields == null) {
					fields = new ArrayList<>();
				}

				fields.add(refRespArg);
			}
		}

		return refRespArg;
	}
}
